package com.ternnetwork.oa.service.impl.work;

import com.ternnetwork.commons.model.http.BaseResponse;
import com.ternnetwork.commons.utils.DateUtils;
import com.ternnetwork.core.accesscontroll.entity.User;
import com.ternnetwork.core.accesscontroll.service.UserService;
import com.ternnetwork.oa.dto.work.ReportAddDto;
import com.ternnetwork.oa.dto.work.ReportEditDto;
import com.ternnetwork.oa.entity.note.Note;
import com.ternnetwork.oa.entity.note.NoteCategory;
import com.ternnetwork.oa.entity.settings.UserRelationship;
import com.ternnetwork.oa.entity.settings.UserRelationshipId;
import com.ternnetwork.oa.entity.work.Report;
import com.ternnetwork.oa.enums.messages.ReportMessages;
import com.ternnetwork.oa.enums.settings.UserRelationshipType;
import com.ternnetwork.oa.enums.work.ReportType;
import com.ternnetwork.oa.repository.settings.UserRelationshipRepository;
import com.ternnetwork.oa.repository.work.ReportRepository;
import com.ternnetwork.oa.service.work.ReportService;
import com.ternnetwork.oa.vo.work.ReportVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;


@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private ReportRepository reportRepository;
    @Autowired
    private UserService userService;

    @Autowired
    private UserRelationshipRepository userRelationshipRepository;



    @Override
    public BaseResponse add(ReportAddDto dto, String username) {

        BaseResponse  baseResponse=checkProperties(dto);

        if(baseResponse.getStatus().intValue()==0) {
            return baseResponse;
        }

        Report report=new Report();

        BeanUtils.copyProperties(dto,report);

        User loginUser=userService.findByName(username);

        setTimeAndType(dto, report);

        if(report.getType().equals(ReportType.WEEK)&&!DateUtils.getWeekOfDate(report.getStart()).equals("星期五")){

            baseResponse.setFailed(ReportMessages.FAILED_MESSAGE_WEEK_REPORT_SHOULD_BE_AT_FRIDAY.getName());
        }

        long totalCount=reportRepository.getCountByDate(loginUser.getId(),report.getDate(),report.getType());

        if(totalCount>0L){
           baseResponse.setFailed(getFailedMessageByType(report));
           return baseResponse;
        }

        report.setCreatedById(loginUser.getId());

        reportRepository.saveAndFlush(report);

        baseResponse.setSccucess();

        return baseResponse;
    }



    @Override
    public BaseResponse update(ReportEditDto dto, String username) {

        BaseResponse  baseResponse=checkProperties(dto);

        if(baseResponse.getStatus().intValue()==0) {

            return baseResponse;
        }

        Optional<Report> optional=reportRepository.findById(dto.getId());

        if(optional.equals(Optional.empty())){

            baseResponse.setFailedForObjectNotExist();

            return baseResponse;
        }
        Report report=optional.get();

        User loginUser=userService.findByName(username);

        if(report.getCreatedById()!=loginUser.getId()){

            baseResponse.setFailedForObjectNotBelongsToLoginUser();

            return baseResponse;
        }

        BeanUtils.copyProperties(dto,report);

        report.setUpdatedById(loginUser.getId());

        report.setUpdateTime(new Date());


        reportRepository.saveAndFlush(report);

        baseResponse.setSccucess();

        return baseResponse;
    }

    @Override
    public BaseResponse deleteById(Long id, String username) {

        BaseResponse  baseResponse=new BaseResponse();

        Optional<Report> optional=reportRepository.findById(id);

        if(optional.equals(Optional.empty())){

            baseResponse.setFailedForObjectNotExist();

            return baseResponse;
        }

        Report report=optional.get();

        User loginUser=userService.findByName(username);

        if(report.getCreatedById()!=loginUser.getId()){

            baseResponse.setFailedForObjectNotBelongsToLoginUser();

            return baseResponse;
        }

        reportRepository.delete(report);

        baseResponse.setSccucess();

        return baseResponse;
    }

    @Override
    public BaseResponse findAll(String start, String end, String username) {

        User loginUser=userService.findByName(username);

        Long loginUserId=loginUser.getId();

        return findAll(start, end,loginUserId);
    }

    @Override
    public BaseResponse findAll(String start, String end, Long userId) {

        List<Report> reportList=reportRepository.findAll(userId,DateUtils.parseDate(start,DateUtils.FORMAT_DATE_TIME_DEFAULT),DateUtils.parseDate(end,DateUtils.FORMAT_DATE_TIME_DEFAULT));

        List<ReportVo> reportVoList=new ArrayList<>();

        for(Report report:reportList){

            ReportVo reportVo=new ReportVo();

            BeanUtils.copyProperties(report,reportVo);

            reportVo.setStart(DateUtils.format(report.getStart(),DateUtils.FORMAT_DATE_TIME_DEFAULT));

            reportVo.setEnd(DateUtils.format(report.getEnd(),DateUtils.FORMAT_DATE_TIME_DEFAULT));

            reportVo.setType(report.getType().name());

            reportVo.setReportDate(report.getDate());

            reportVo.setTitle(report.getType().getName());

            reportVoList.add(reportVo);
        }

        BaseResponse baseResponse=new BaseResponse();

        baseResponse.setSccucess(reportVoList);

        return baseResponse;
    }


    @Override
    public BaseResponse toMeFindAll(String start, String end, Long userId,String loginUsername) {

        BaseResponse baseResponse=new BaseResponse();

        User user=userService.findByName(loginUsername);

        UserRelationshipId id =new UserRelationshipId(userId,user.getId(), UserRelationshipType.WORK_REPORT);

        Optional<UserRelationship> old= userRelationshipRepository.findById(id);

        if(old.equals(Optional.empty())) {

            baseResponse.setFailedForObjectNotBelongsToLoginUser();

            return baseResponse;
        }

        return findAll(start, end, userId);
    }


    private void setTimeAndType(ReportAddDto dto, Report report) {

        report.setStart(DateUtils.parseDate(dto.getStart(), DateUtils.FORMAT_DATE_TIME_DEFAULT));

        report.setEnd(DateUtils.parseDate(dto.getEnd(), DateUtils.FORMAT_DATE_TIME_DEFAULT));

        report.setDate(Long.parseLong(DateUtils.format(report.getStart(),DateUtils.FORMAT_DATE_YYYYMMDD)));

        report.setType(ReportType.valueOf(dto.getType()));
    }

    private String getFailedMessageByType(Report report){
        if(report.getType().equals(ReportType.DAY)){
            return ReportMessages.FAILED_MESSAGE_EXIST_SAME_DAY_REPORT.getName();
        }
        if(report.getType().equals(ReportType.MONTH)){
          return ReportMessages.FAILED_MESSAGE_EXIST_SAME_MONTH_REPORT.getName();
        }
        return ReportMessages.FAILED_MESSAGE_EXIST_SAME_WEEK_REPORT.getName();
    }

    private BaseResponse checkProperties (ReportAddDto t) {

        BaseResponse  baseResponse=new BaseResponse();

        if(StringUtils.isEmpty(t.getWorkContent())) {
            baseResponse.setFailed(ReportMessages.FAILED_MESSAGE_CONTENT_CAN_NOT_BE_EMPTY.getName());
            return baseResponse;
        }

        if(StringUtils.isEmpty(t.getStart())) {
            baseResponse.setFailed(ReportMessages.FAILED_MESSAGE_START_CAN_NOT_BE_EMPTY.getName());
            return baseResponse;
        }
        baseResponse.setSccucess();
        return baseResponse;
    }

    private BaseResponse checkProperties (ReportEditDto t) {

        BaseResponse  baseResponse=new BaseResponse();

        if(StringUtils.isEmpty(t.getWorkContent())) {
            baseResponse.setFailed(ReportMessages.FAILED_MESSAGE_CONTENT_CAN_NOT_BE_EMPTY.getName());
            return baseResponse;
        }

        baseResponse.setSccucess();
        return baseResponse;
    }
}
